﻿// © Benn Eichhorn 2010
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Algobox.Feeds.Finance.Bats.PitchClient.Messages
{
    /// <summary>
    /// Singleton Bats Order Cancel message
    /// </summary>
    public class OrderCancel : IMessage
    {
        private OrderCancel() { }

        private static OrderCancel _instance = new OrderCancel();

        /// <summary>
        /// Get's the singleton instance of the OrderCancel class
        /// </summary>
        /// <returns>Current OrderCancel</returns>
        public static OrderCancel GetInstance() { return _instance; }

        public char MessageType { get { return 'C'; } }
        
        /// <summary>
        /// Milliseconds since midnight
        /// </summary>
        public int TimeStampMillis;

        /// <summary>
        /// Slow, calculates current TimeStamp from TimeStampMillis
        /// </summary>
        public DateTime TimeStamp { get { return BatsMessageParser.Date.AddMilliseconds(TimeStampMillis); } }

        /// <summary>
        /// Day unique order reference number in Base-36 encoding
        /// </summary>
        public string OrderReference;
        
        /// <summary>
        /// Number of shares canceled
        /// </summary>
        public ulong CanceledShares;
                
        public override string ToString()
        {
            return String.Format("IMessage->OrderCancel: OrderReference={0},CanceledShares={1},TimeStamp={2}", OrderReference, CanceledShares, TimeStamp);
        }


        // Order Cancel
        const int S_X_ORDERREF_LOC = 10;
        const int S_X_ORDERREF_LEN = 12;
        const int S_X_SHARES_LOC = 22;
        const int S_X_SHARES_LEN = 6;

        // Order Cancel Long
        const int S_x_ORDERREF_LOC = 10;
        const int S_x_ORDERREF_LEN = 12;
        const int S_x_SHARES_LOC = 22;
        const int S_x_SHARES_LEN = 10;


        internal static IMessage ParseShort(ref string inbound)
        {
            // get sequenced data message timestamp
            if (!Int32.TryParse(inbound.Substring(BatsMessageParser.S_TIMESTAMP_LOC, BatsMessageParser.S_TIMESTAMP_LEN), out _instance.TimeStampMillis))
            {
                Messages.Error message = Messages.Error.GetInstance("Sequenced data message failed to parse TimeStamp millis as Double", ref inbound);
                return message;
            }
            if (!UInt64.TryParse(inbound.Substring(S_X_SHARES_LOC, S_X_SHARES_LEN), out _instance.CanceledShares))
            {
                return Messages.Error.GetInstance("OrderCancel (long) failed to parse CanceledShares as Int64", ref inbound);
            }

            _instance.OrderReference = inbound.Substring(S_X_ORDERREF_LOC, S_X_ORDERREF_LEN);

            return _instance;
        }


        internal static IMessage ParseLong(ref string inbound)
        {
            // get sequenced data message timestamp
            if (!Int32.TryParse(inbound.Substring(BatsMessageParser.S_TIMESTAMP_LOC, BatsMessageParser.S_TIMESTAMP_LEN), out _instance.TimeStampMillis))
            {
                Messages.Error message = Messages.Error.GetInstance("Sequenced data message failed to parse TimeStamp millis as Double", ref inbound);
                return message;
            }
            if (!UInt64.TryParse(inbound.Substring(S_x_SHARES_LOC, S_x_SHARES_LEN), out _instance.CanceledShares))
            {
                return Messages.Error.GetInstance("OrderCancel (long) failed to parse CanceledShares as Int64", ref inbound);                
            }

            _instance.OrderReference = inbound.Substring(S_x_ORDERREF_LOC, S_x_ORDERREF_LEN);

            return _instance;
        }


        /// <summary>
        /// Deep clone
        /// </summary>
        /// <returns></returns>
        public OrderCancel Clone()
        {
            OrderCancel clone = new OrderCancel();
            clone.CanceledShares = _instance.CanceledShares;
            clone.OrderReference = _instance.OrderReference;
            clone.TimeStampMillis = _instance.TimeStampMillis;
            return clone;
        }
    }
}
